<template>
  <div class="login_container">
    <div class="cover"></div>
    <div class="aimate">
      <Particles
        style="height:100%;width:100%;"
        id="tsparticles"
       :particlesInit="particlesInit"
        :options="options"
    />
    </div>
  
    <div class="login_box">
      <div class="login_box_left">
          <header>{{ showTime }} {{currentDay}}</header>
          <main>
            <div class="title">MegaSensys</div>
            <aside>
              <p>
                 智能
              </p>
              <div class="desc">感知系统</div>
            </aside>
           
          </main>
      </div>
      <div class="login_box_right">
        <header>登录</header>
          <!-- 表单提交区域-->
      <el-form :rules="loginFormRules" ref="loginFormRef" label-width="0px" class="login_form" :model="loginForm">
        <!-- 用户名 -->
        <el-form-item prop="username">
          <el-input
            style="height: 40px;"
            v-model="loginForm.username"
            class="w-50 m-2"
            placeholder="账号"
            :prefix-icon="User"
      >
    </el-input>
        </el-form-item>
        <!-- 密码-->
        <el-form-item prop="password">
          <el-input
            style="height: 40px;"
            v-model="loginForm.password"
            class="w-50 m-2"
            type="password"
            placeholder="密码"
            :prefix-icon="Lock"
      >
    </el-input>
        </el-form-item>
        <!-- 验证码 -->
        <el-form-item style="display: flex;justify-content: space-between;">
          <el-input 
            placeholder="验证码" 
            v-model="code"
            :prefix-icon="Position"
            style="height: 40px;width: 65%;margin-right: 5%;"
          />
          <div class="captcha-image" style="height: 40px;width: 30%;border: 1px solid #ccc;" @click="resetCode">
            <canvas ref="capatchCanvas" style="height:100;width:100%;"></canvas>
          </div>
        </el-form-item>
      </el-form>
      <!--  按钮区-->
      <div class="btns">
        <el-button type="primary" @click="login" :loading="loginLoading">登录</el-button>
      </div>
      <p style="text-align: right;padding-top:10px;">
        <!-- 忘记密码 -->
        <el-text class="mx-1 my_forget" type="primary" @click="forgetPass">忘记密码</el-text>
      </p>
      </div>
    
    </div>
  </div>

  <!-- 用户忘记密码 -->
  <el-dialog
  title="找回密码"
  v-model="forgetVisable"
  width="30%"
  draggable
  center>
  <el-form 
    ref="ruleForgetPass"
    :rules="forgetRules"
    :model="forgetUserInfo"
  >
  <el-form-item prop="email" label-width="90px" label="邮箱">
    <el-input v-model="forgetUserInfo.email"></el-input>
  </el-form-item>
  <el-form-item prop="password" label="密码" label-width="90px">
    <el-input type="password" v-model="forgetUserInfo.password"></el-input>
  </el-form-item>
  <el-form-item prop="resetPassword" label="重复密码" label-width="90px">
    <el-input type="password" v-model="forgetUserInfo.resetPassword"></el-input>
  </el-form-item>
  <el-form-item  prop="code" label-width="90px" label="验证码" style="display: flex;">
    <el-input style="width: 60%;margin-right: 20px;" v-model="forgetUserInfo.code"></el-input>
    <el-button type="primary" @click="sendMsg" v-if="isAble">发送验证码</el-button>
    <el-button type="primary" v-else disabled>{{ sendTime }}</el-button>
  </el-form-item>
  </el-form>
  <template #footer>
      <div class="dialog-footer">
        <el-button @click="forgetVisable = false">取消</el-button>
        <el-button type="primary" @click="confirm_by_email">
          确定
        </el-button>
      </div>
    </template>
</el-dialog>
</template>

<script setup lang="ts">

  // 定义邮箱正则表达式
  const emailReg:RegExp = new RegExp(/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/)
  import { User } from '@element-plus/icons-vue'
  import {IhttpReturn, loginType} from '../until/interface'
  import {ref,reactive, onMounted,onUnmounted} from 'vue'
  import type {FormRules} from 'element-plus'
  import { Lock,Position } from '@element-plus/icons-vue'
  import { getCurrentInstance } from 'vue'
  import { userStore } from '../store/user'
  import router from '../router';
  import {loadFull} from 'tsparticles'
  import type { Engine } from 'tsparticles-engine'
// 定义验证码
let code = ref<string>("") // 用户输入的验证码
let randomCode = ref<any>("") // 系统生成的验证码
let capatchCanvas = ref()
let canvas = ref<any>(null) // 验证码实列
let ctx = ref<any>(null)
const resetView = () => {
  let clientWidth = document.body.clientWidth
      if (clientWidth < 1400) {
        console.log("小屏幕")
        setTimeout(() => {
          document.documentElement.style.fontSize = "150px"
        }, 300);
      }
}
onMounted(() => {
  // 刷新验证码
  drawCaptcha()
  // 开始定时器
  startTimer()
  resetView()
  // 屏幕适配问题
  window.onresize = function() {
      resetView()
    }
})

/**编写定时器函数 */
import Tool from '../until/tool'
import { time } from 'echarts';
let showTime = ref<string>() // 显示的时间
let timer = reactive(null)
let currentDay = ref<string|number>("") // 当前是礼拜几
let dayList:string[] = ["星期一","星期二","星期三","星期四","星期五","星期六","星期天"]
const startTimer = () => {
  timer = setInterval(() => {
     currentDay.value = dayList[new Date().getDay() - 1]
    showTime.value = Tool.tool.getTimeStr(new Date())
  },1000)
}
onUnmounted(() => {
  clearInterval(timer)
})
//重新生成验证码
const resetCode = () => {
  ctx.value.clearRect(0,0,canvas.value.width,canvas.value.height)
  const captchaText = generateCaptchaText()
  randomCode.value = captchaText
  //@ts-ignore
  ctx.value.fillText(captchaText,canvas.value.width/2 - 48,canvas.value.height/2)
  proxy.$message({showClose: true,message: "切换验证码成功",type: "success"})
}
// 随机生成验证码
const drawCaptcha = () => {
      canvas.value = capatchCanvas.value
      //@ts-ignore
      ctx.value = canvas.value.getContext('2d')

      const captchaText = generateCaptchaText()
      randomCode.value = captchaText
      console.log(randomCode.value)
      //@ts-ignore
      ctx.value.fillStyle = '#8786bf';
      //@ts-ignore
      ctx.value.font = "68px serif"
      //@ts-ignore
      ctx.value.fillText(captchaText, canvas.value.width/2 - 48, canvas.value.height/2)
      // TODO: 添加多种颜色以及弯曲和扭曲效果，增强验证码安全性
    }
const generateCaptchaText = function():string {
  const chars = '0123456789abcdefghijklmnopqrstuvwxyz'
  let captchaText = ''
      for (let i = 0; i < 4; i++) {
        captchaText += chars[Math.floor(Math.random() * chars.length)];
      }
      return captchaText
}
// 定义粒子动画
const particlesInit = async (engine: Engine) => {
  await loadFull(engine);
};
const options = reactive({
  fpsLimit: 600,
  interactivity: {
    events: {
      onClick: {
        enable: true,
        mode: "push", // 可用的click模式有: "push", "remove", "repulse", "bubble"。
      },
      onHover: {
        enable: true,
        mode: "grab", // 可用的hover模式有: "grab", "repulse", "bubble"。
      },
      resize: true,
    },
    modes: {
      grap: {
        distance: 300,
        duration: 1,
        opacity: 1,
        size: 40,
      },
      push: {
        quantity: 4,
      },
      repulse: {
        distance: 200,
        duration: 0.4,
      },
    },
  },
  particles: {
    color: {
      value: "#ffffff",
    },
    links: {
      color: "#ffffff", // '#dedede'。线条颜色。
      distance: 120, // 线条长度
      enable: true, // 是否有线条
      opacity: 0.37, // 线条透明度。
      width: 1.4, // 线条宽度。
    },
    collisions: {
      enable: false,
    },
    move: {
      direction: "none",
      enable: true,
      outMode: "bounce",
      random: false,
      speed: 1, // 粒子运动速度。
      straight: false,
      out_mode: "out",
      attract: {
          "enable": false,
          "rotateX": 600,
          "rotateY": 1200
        }
    },
    number: {
      density: {
        enable: true,
        value_area: 800
      },
      value: 80, // 粒子数量。
    },
    opacity: {
      value: 0.4
    },
    shape: {
      type: "star", // 可用的粒子外观类型有："circle","edge","triangle", "polygon","star"
    },
    size: {
      random: true,
      value: 3, // 粒子大小。
    },
  },
  detectRetina: true,
});
  
  let store = userStore()
  let {proxy} = getCurrentInstance()
  let loginFormRef = ref() // 登录表单的引用
  let loginLoading = ref<boolean>(false) // 登录的状态
  // 用户的登录参数
  let loginForm = reactive<loginType>({
    username: "",
    password: ""
  }); 
      // 用户登录
  const login = ():void =>  {
    loginFormRef.value.validate(async (item:any) => {
       if (!item) return proxy.$message({showClose: true,message: "前按照规则进行填写",type: "warning"})
       if (code.value == '') return proxy.$message({showClose: true,message: "验证码不能为空",type: "warning"})
       if (code.value !== randomCode.value) return proxy.$message({showClose: true,message: "验证码填写错误",type:"warning"})
       let {data:res}: {data:IhttpReturn} = await proxy.$outsideHttp.post("/user/login",loginForm)
       if (res.code !== 200)  return proxy.$message({showClose: true,message: res.msg,type: "warning"})
       proxy.$message({showClose: true,message: res.msg,type: "success"})
       store.initUser(res.data)
       router.push("/home")
       // 修改数据库用户的登录状态
       await proxy.$outsideHttp.put("/user/updateLoginStatus",{status: 1,token: res.data.token})

    })
  }
  // 验证密码
  const validatePass = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('密码不能为空'))
  } else if (!(/^[a-zA-Z0-9]{6,12}$/.test(value))) {
    callback(new Error("密码为6-12位，有数字和字母组成"))
  } else {
    callback()
  }
}
const validateUser = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('用户名不能为空'))
  } else if (!(/^[a-zA-Z0-9_-]{4,16}$/.test(value))) {
    callback(new Error("4到16位（字母，数字，下划线，减号"))
  } else {
    callback()
  }
}
  let loginFormRules = reactive<FormRules<typeof loginForm>>({
    username: [{ validator: validateUser, trigger: 'blur' }],
    password: [{ validator: validatePass, trigger: 'blur' }],
  })

  // 忘记密码
    // 验证邮箱
    const validateEmail = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('用户名不能为空'))
  } else if (!(emailReg.test(value))) {
    callback(new Error("邮箱错误，请重新输入邮箱"))
  } else {
    callback()
  }
}
  let forgetVisable = ref(false) // 控制忘记密码对话框的显示或者隐藏
  const forgetPass = () => {
    console.log("忘记密码")
    forgetVisable.value = true
  }
  let ruleForgetPass = ref() 
  let forgetRules = reactive({
    email: [{validator: validateEmail,trigger: 'blur'}],
    password: [{validator: validatePass,trigger: "blur"}],
    resetPassword: [{validator: validatePass,trigger: "blur"}],
    code: [
      {required:true,message: "验证码不能为空",trigger: "blur"},
      {min: 3,max:5,message: "验证码为四位",trigger: "blur"}
    ]
  }) 
  let forgetUserInfo = reactive({
      email: "", // 邮箱地址
      password: "", // 修改的密码
      resetPassword: "", // 重新输入密码
      getCode: "", // 从后台获取到的验证码
      code: "" //验证码
  })
  let isAble = ref(true)
  let sendTime = ref(60)
  // 发送邮箱
  const sendMsg = async () => {
    if (emailReg.test(forgetUserInfo.email)) {
      // 发送邮箱接口
      let {data: res}: {data: IhttpReturn} = await proxy.$outsideHttp.post("/user/sendEmail",{email: forgetUserInfo.email})
      if (res.code !== 200) return proxy.$message({type:"info",message: res.msg})
      forgetUserInfo.getCode = res.data.code // 获取的验证码，判断用户是否输入正确验证码来验证用户的身份
      proxy.$message({type: "success",message: "发送成功，注意查收邮箱"})
      isAble.value = false
      sendTime.value = 60
      let timer = setInterval(() => {
      if (sendTime.value > 0) {
        sendTime.value --
      } else {
        clearInterval(timer)
        isAble.value = true
      }
    },1000)
   } else {
      proxy.$message({type:"warning",message: "邮箱格式错误"})
   }
  }
  // 确定修改密码
  const confirm_by_email = () => {
      // 前端校验
      ruleForgetPass.value.validate(async (res:any) => {
         if (!res) return proxy.$message({type:"error",message: "请按照规定进行填写"})
         if (forgetUserInfo.password !== forgetUserInfo.resetPassword) return proxy.$message({type: "warning",message: "二次密码不一致"})
         if (forgetUserInfo.getCode !== forgetUserInfo.code) return proxy.$message({type: "warning",message: "验证码填写错误"})
         // 发送请求区修改用户的密码
         let result = await proxy.$outsideHttp.post("/user/byEmailUpdatePassword",{email: forgetUserInfo.email,password: forgetUserInfo.password,code: forgetUserInfo.code})
         if (result.data.code !== 200) return proxy.$message({type: "error",message: "修改密码失败"})
         proxy.$message({type: "success",message: "修改密码成功"})
         isAble.value = true
         forgetVisable.value = false
         ruleForgetPass.value.resetFields()
      })
  }
 
</script>

<style lang="less" scoped>


.login_container {
  height: 100%;
  // background-color: #081638;
  background: linear-gradient(to right,#081638,#8b87cc,#081638);
  .cover {
    background: #d8d8d8;
    opacity: .1;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
  }
  .aimate {
    width: 100%;
    height: 100%;
  }
}
.login_box {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 902px;
  height: 450px;
  background-color: #fff;
  border-radius: 3px;
  display: flex;
  .login_box_left {
    flex: 1;
    padding: 0 20px;
    background-color: #4ba0fc;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    header {
      height: 60px;
      line-height: 60px;
      color: #fff;
      font-size: 16px;
    }
    main {
      height: 70%;
      padding: 0 30px;
      color:#fff;
      .title {
          font-size: 22px;
          margin-bottom: 5px;
          width: 55%;
          text-align: center;
        }
      aside {
        width: 100%;
        height: 160px;
        display: flex;
        p {
          font-size: 16px;
          height: 160px;
          width: 55%;
          border-top: 10px solid #fff;
          border-left: 10px solid #fff;
          border-bottom: 10px solid #fff;
          position: relative;
          display: flex;
          align-items: center;
          font-size: 38px;
          justify-content: center;
        &::before {
          content: "";
          position: absolute;
          display: inline-block;
          background-color: #fff;
          height: 30px;
          top: -1px;
          right: 0;
          width: 10px;
        }
        &::after {
          content: "";
          position: absolute;
          display: inline-block;
          background-color: #fff;
          height: 30px;
          bottom: -1px;
          right: 0;
          width: 10px;
        }
        }
        .desc {
          display: flex;
          align-items: center;
          font-size: 26px;
          color: #fff;
        }
      }
      
    }
  }
  .login_box_right {
    width: 100%;
    flex: 1;
    padding: 40px 40px;
    header {
      height: 50px;
      line-height: 50px;
      text-align: center;
      font-size: 28px;
      letter-spacing: 3px;
      color: #54a2f9;
    }
    .login_form {
      box-sizing: border-box;
      height: 60%;
      padding-top: 20px;
  }
  .btns {
      margin-top: 10px;
      display: flex;
      justify-content: center;
      height: 40px;
      width: 100%;
      .el-button {
        height: 40px;
        width: 80%;
      }
  }
  }
 
}

 .my_forget:hover {
  cursor: pointer;
 }
</style>